home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / GRAPHICS / NANOTECH.ZIP / PIX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-11  |  13.6 KB  |  594 lines

  1. /*
  2.  
  3. NanoTech - a 3d game engine
  4. Copyright (C) 1996  Sean Lane Fuller
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20. Sean Lane Fuller
  21. 124 Autumn Lane
  22. Tullahoma, TN 37388
  23. 615-393-4550
  24. email: fuller@edge.net
  25.  
  26. */
  27.  
  28.  
  29. #include <dos.h>
  30. #include <mem.h>
  31. #include <bios.h>
  32. #include <math.h>
  33. #include <stdarg.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <graph.h>
  38. #include "pix.h"
  39. #include "keyboard.h"
  40. #include "sbuffer.h"
  41.  
  42. int background;
  43. unsigned int pix_tbl[MAXNUMYPIXELS];
  44.  
  45. char *pix_mem;
  46. char *pix_buf;
  47. unsigned char *screen = (unsigned char *)0xa0000;
  48.  
  49. void pix_lineclip( int x1, int y1, int x2, int y2, int color  );
  50. #define PIX_MAXVERTS 10
  51.  
  52. #define INPUT_STATUS_1  0x3da   //Input Status 1 register
  53. #define BORDER_COLOR 0x7b
  54. #define BORDER_DELTA 3
  55.  
  56. #define fixtoint(x) ((int)(x))
  57. #define fixtodbl(x) (x)
  58. #define inttofix(x) ((float)(x))
  59. #define dbltofix(x) (x)
  60.  
  61. void refr(long *dest, long *source, int length);
  62. #pragma aux refr = " rep movsd " parm [EDI] [ESI] [ECX] modify [EDI ESI ECX];
  63.  
  64. struct videoconfig vc;
  65.  
  66. void pix_refresh() {
  67.    int c;
  68.    static int a=1, v=0;
  69.    // wait for retrace
  70. //   do {
  71. //      c = inp(0x3da);
  72. //   } while (!(c & 0x08) && !keys[ESC]);
  73.  
  74.    if (VIDMODE == _MRES256COLOR)
  75.       refr(screen, pix_mem, 16000);
  76.    else
  77.       _putimage(0, 0, pix_buf, _GPSET);
  78. }
  79.  
  80. /******************************************************************************
  81.  * set palette registers
  82.  *****************************************************************************/
  83. void pix_setup_palette(float f)
  84. {
  85.    static char first = 1;
  86.    char ch;
  87.    float cd[16][3] = { { 64, 0, 0 }, {0, 64, 0}, {0, 0, 64},
  88.       {64, 64, 0}, {64, 0, 64}, {0, 64, 64}, {64, 64, 64}, {64, 32, 16},
  89.          { 64, 32, 0 }, {32, 64, 0}, {0, 32, 64},
  90.       {64, 64, 32}, {64, 32, 64}, {32, 64, 64}, {64, 32, 64}, {32, 32, 16}};
  91.    int c, i, dx = 0x3c8, bx = 0, cx;
  92.    FILE *fp;
  93.  
  94. /*
  95.    asm mov dx,INPUT_STATUS_1
  96. WaitDE:
  97.    asm in      al,dx
  98.    asm test    al,08h
  99.    asm jz     WaitDE
  100. */
  101.  
  102.    for (cx=0; cx<256; cx++)
  103.    {
  104.       c = cx/16;
  105.       i = cx%16;
  106.       outp(dx, bx);
  107.       dx++;
  108.       outp(dx, (int)((cd[c][0]/16.0*f)*i));
  109.       outp(dx, (int)((cd[c][1]/16.0*f)*i));
  110.       outp(dx, (int)((cd[c][2]/16.0*f)*i));
  111.       dx--;
  112.       bx++;
  113.    }
  114.    if (first)
  115.    {
  116.       fp = fopen("palette.pal", "wb");
  117.       for (cx = 0; cx < 256; cx++)
  118.       {
  119.          c = cx / 16;
  120.          i = cx % 16;
  121.          ch = cd[c][0] * i;
  122.          fwrite(&ch, 1, 1, fp);
  123.          ch = cd[c][0] * i;
  124.          fwrite(&ch, 1, 1, fp);
  125.          ch = cd[c][0] * i;
  126.          fwrite(&ch, 1, 1, fp);
  127.       }
  128.       fclose(fp);
  129.       first = 0;
  130.    }
  131. }
  132.  
  133. void pix_init()
  134. {
  135.    union REGS r;
  136.    unsigned int i;
  137.    _setvideomode(VIDMODE);
  138.    _setfillmask(_GPSET);
  139.    _setplotaction(_GPSET);
  140.    _getvideoconfig(&vc);
  141.    pix_buf = malloc(_imagesize(0, 0, MAXX, MAXY));
  142.    pix_mem = &pix_buf[_imagesize(0, 0, MAXX, MAXY) - NUMXPIXELS*NUMYPIXELS];
  143.    _getimage(0, 0, MAXX, MAXY, pix_buf);
  144.    for (i=0; i<=MAXY; i++) pix_tbl[i] = i * (MAXX+1);
  145.    pix_setup_palette(1.0);
  146.    pix_cls(0);
  147. }
  148.  
  149. #define pix_addr(x, y) (pix_tbl[y] + x)
  150.  
  151. void pix_term()
  152. {
  153. //   union REGS r;
  154. //   r.h.ah = 0x00;
  155. //   r.h.al = 3;
  156. //   int386(0x10, &r, &r);
  157.    _setvideomode(_TEXTC80);
  158. }
  159.  
  160. #define pix_set(x,y,color) pix_mem[pix_addr((x),(y))] = color
  161.  
  162. void pix_pset(int x, int y, int color)
  163. {
  164.    pix_set(x, y, color);
  165. }
  166.  
  167. void pix_cls(int background)
  168. {
  169.    memset(pix_mem, background, (unsigned int)(MAXX+1)*(unsigned int)(MAXY+1));
  170. }
  171.  
  172. void pix_line(int xa, int ya, int xb, int yb, short color)
  173. {
  174.    int dx, dy, absdx, absdy, i, pa;
  175.    short pos;
  176.    int g, r, c, inc1, inc2, f, offs;
  177.    dy = yb - ya;
  178.    if ( dy == 0 )
  179.    {
  180.       /* Horizontal lines */
  181.       if (xb < xa)
  182.       {
  183.          for(; xb <= xa; xb++ )
  184.          {
  185.             pix_set(xb, ya, color);
  186.          }
  187.       }
  188.       else
  189.       {
  190.          for(; xa <= xb; xa++ )
  191.          {
  192.             pix_set(xa, ya, color);
  193.          }
  194.       }
  195.       return;
  196.    }
  197.    dx = xb - xa;
  198.    if ( dx == 0 )
  199.    {
  200.       /* Vertical Lines */
  201.       if (yb < ya)
  202.       {
  203.          for(; yb <= ya; yb++, pa+=80 )
  204.          {
  205.             pix_set(xa, yb, color);
  206.          }
  207.       }
  208.       else
  209.       {
  210.          for(; ya <= yb; ya++, pa += 80 )
  211.          {
  212.             pix_set(xa, ya, color);
  213.          }
  214.       }
  215.       return;
  216.    }
  217.    if ( dx > 0 )
  218.    {
  219.       if ( dy < 0 ) pos = 0;
  220.       else pos = 1;
  221.    }
  222.    else
  223.    {
  224.       if ( dy < 0 ) pos = 1;
  225.       else pos = 0;
  226.    }
  227.    if ( abs( dx ) > abs( dy ) )
  228.    {
  229.       if ( dx > 0 ) {  c = xa; r = ya; f = xb; }
  230.       else {  c = xb; r = yb; f = xa; }
  231.       inc1 = abs( dy + dy );
  232.       g = abs( dy ) * 2 - abs( dx );
  233.       inc2 = ( abs( dy ) - abs( dx ) ) * 2;
  234.       if ( pos )
  235.       {
  236.          while ( c <= f )
  237.          {
  238.             pix_set(c, r, color);
  239.             c++;
  240.             if ( g >= 0 ) { r++; g += inc2; }
  241.             else g += inc1;
  242.          }
  243.          return;
  244.       }
  245.       else
  246.       {
  247.          while ( c <= f )
  248.          {
  249.             pix_set(c, r, color);
  250.             c++;
  251.             if ( g > 0 ) { r--; g += inc2; }
  252.             else g+=inc1;
  253.          }
  254.          return;
  255.       }
  256.    }
  257.    else
  258.    {
  259.       if ( dy > 0 ) { c=ya; r=xa; f=yb; }
  260.       else { c=yb; r=xb; f=ya; }
  261.       inc1 = abs( dx + dx );
  262.       g = abs( dx ) * 2 - abs( dy );
  263.       inc2 = ( abs( dx ) - abs( dy )) * 2;
  264.       if ( pos )
  265.       {
  266.          if (c <= f)
  267.          {
  268.             pix_set(r, c, color);
  269.             LOOP3:
  270.                c++;
  271.                if ( g >= 0 ) {
  272.                   r++; g+=inc2;
  273.                   if (c > f) goto EXIT_LOOP3;
  274.                   pix_set(r, c, color);
  275.                }
  276.                else
  277.                {
  278.                   g+=inc1;
  279.                   if (c > f) goto EXIT_LOOP3;
  280.                   pix_set(r, c, color);
  281.                }
  282.                goto LOOP3;
  283.             EXIT_LOOP3:
  284.                ;
  285.          }
  286.          return;
  287.       }
  288.       else
  289.       {
  290.          if (c <= f)
  291.          {
  292.             pix_set(r, c, color);
  293.             LOOP4:
  294.                c++;
  295.                if ( g >= 0 ) {
  296.                   r--; g+=inc2;
  297.                   if (c > f) goto EXIT_LOOP4;
  298.                   pix_set(r, c, color);
  299.                }
  300.                else
  301.                {
  302.                   g+=inc1;
  303.                   if (c > f) goto EXIT_LOOP4;
  304.                   pix_set(r, c, color);
  305.                }
  306.                goto LOOP4;
  307.             EXIT_LOOP4:
  308.                ;
  309.          }
  310.       }
  311.    }
  312. }
  313.  
  314. void pix_disp_char(int c, unsigned int x, unsigned int y, int fgd, int bkgd)
  315. {
  316.    unsigned char *ctbl = (unsigned char *)0xffa6e;
  317.    int ctbli = c << 3;
  318.    unsigned int scri = pix_addr(x, y);
  319.    unsigned int i, j, b;
  320.    for (i=0; i<8; i++)
  321.    {
  322.       b = ctbl[ctbli];
  323.       for (j=0; j<4; j++)
  324.       {
  325.          if (b & 0x080) pix_mem[scri] = fgd /* - j */;
  326.          else if (bkgd != 0) pix_mem[scri] = bkgd;
  327.          scri++;
  328.          b <<= 2;
  329.       }
  330.       if (bkgd != 0) pix_mem[scri] = bkgd;
  331.       ctbli++;
  332.       scri += (MAXX + 1) - 4;
  333.    }
  334. }
  335.  
  336. void pix_disp_str(char *s, int x, int y, int fgd, int bkgd)
  337. {
  338.    int ox = x;
  339.    while (*s)
  340.    {
  341.       if (*s == '\n')
  342.       {
  343.          x = ox;
  344.          y += 8;
  345.       }
  346.       else
  347.       {
  348.          pix_disp_char(*s, x, y, fgd, bkgd);
  349.          x += 5;
  350.       }
  351.       s++;
  352.    }
  353. }
  354.  
  355.  
  356. void pix_pop_msg(char *format, int fgd, int bkgd)
  357. {
  358.    int i, j, height=1, width=0, x, y;
  359.    char msg[4096];
  360.    char *s;
  361.    va_list argptr;
  362. //   va_start(argptr, bkgd);
  363. //   vsprintf(msg, format, argptr);
  364. strcpy(msg, format);
  365.    i = 0;
  366.    s = msg;
  367.    j = 0;
  368.    // compute dimensions
  369.    while (*s)
  370.    {
  371.       if (*s == '\n')
  372.       {
  373.          if (j > width) width = j;
  374.          j = 0;
  375.          height++;
  376.       }
  377.       else j++;
  378.       s++;
  379.       i++;
  380.    }
  381.    if (j > width) width = j;
  382.    width *= 5;
  383.    height <<= 3;
  384.    y = NUMYPIXELS/2 - height/2;
  385.    x = NUMXPIXELS/2 - width/2;
  386.    pix_disp_str(msg, x + 1, y + 1, 1, bkgd);
  387.    pix_disp_str(msg, x, y, fgd, 0);
  388.    pix_line(x, y, x + width, y, fgd);
  389.    pix_line(x + width, y, x + width, y + height, fgd);
  390.    pix_line(x + width, y + height, x, y + height, fgd);
  391.    pix_line(x, y + height, x, y, fgd);
  392. }
  393.  
  394. void pix_wire( int vert_x[], int vert_y[], int no_verts, int color)
  395. {
  396.    int i, j;
  397.    i = no_verts - 1;
  398.    pix_line(vert_x[i], vert_y[i], vert_x[0], vert_y[0], color);
  399.    i = 0; j = 1;
  400.    while (j < no_verts)
  401.    {
  402.       pix_line(vert_x[i], vert_y[i],
  403.                vert_x[j], vert_y[j], color);
  404.       j++; i++;
  405.    }
  406. }
  407.  
  408. int pix_pop_yn(char *msg, int fgd, int bkgd)
  409. {
  410.    pix_pop_msg(msg, fgd, bkgd);
  411.    pix_refresh();
  412. }
  413.  
  414.  
  415. struct PCXHEADER{
  416.     unsigned char manu, hard, encod, bitpx;
  417.     unsigned int x1, y1, x2, y2;
  418.     unsigned int hres, vres;
  419.     unsigned char palette[48];
  420.     unsigned char vmode, nplanes;
  421.     unsigned int bytesPerLine;
  422.     char unused[128-68];
  423.        } ;
  424.  
  425.  
  426. int getbyte(int *c, int *count, FILE *in)
  427. {
  428.     if (feof(in)) return EOF;
  429.     *c = getc(in) & 0xFF;
  430.     if ((*c & 0xC0) == 0xC0) {
  431.        *count = *c & 0x3F;
  432.        if (feof(in)) return EOF;
  433.        *c = getc(in) & 0xFF;
  434.     }
  435.     else *count = 1;
  436.     return NULL;
  437. }
  438.  
  439. void pix_loadpcx(char *buffer, char *filename, int setup_palette)
  440. {
  441.    int c, count, bx, dx, cx;
  442.    unsigned int i;
  443.    char *scr = buffer;
  444.    FILE *in;
  445.    in = fopen(filename, "rb");
  446.    if (in == NULL) return;
  447.  
  448.    /* setup the palette */
  449.    dx = 0x3c8; bx = 0;
  450.    fseek(in, -768, SEEK_END);
  451.    for (cx=0; cx<256; cx++)
  452.    {
  453.       unsigned char red, green, blue;
  454.       red = getc(in);
  455.       green = getc(in);
  456.       blue = getc(in);
  457.       if (setup_palette)
  458.       {
  459.          outp(dx, bx);
  460.       }
  461.       dx++;
  462.       if (setup_palette)
  463.       {
  464.          outp(dx, red >> 2);
  465.          outp(dx, green >> 2);
  466.          outp(dx, blue >> 2);
  467.       }
  468.       dx--;
  469.       bx++;
  470.    }
  471.    
  472.  
  473.    i = 0;
  474.    rewind(in);
  475.    fseek(in, 128L, SEEK_SET);
  476.    while (getbyte(&c, &count, in) != EOF)
  477.    {
  478.        while (count--) {
  479.          scr[i] = c;
  480.          i++;
  481.          if (i >= (MAXX + 1) * (MAXY + 1)) goto quit;
  482.        }
  483.    }
  484.    quit:
  485.    fclose(in);
  486. }
  487.  
  488. void box(int x1, int y1, int x2, int y2, int c)
  489. {
  490. //   extern char *pix_mem;
  491.    int w, h, i, j, a1, a2;
  492.    if (x2 < 0) return;  
  493.    if (y2 < 0) return;
  494.    if (x1 > MAXX) return;
  495.    if (y1 > MAXY) return;
  496.    if (x1 < 0) x1 = 0;
  497.    if (y1 < 0) { j = -y1; y1 = 0; } else j = 0;
  498.    if (x2 > MAXX) x2 = 319;
  499.    if (y2 > MAXY) y2 = MAXY;
  500.    w = x2 - x1 + 1;
  501.    h = y2 - y1 + 1;
  502.    a1 = pix_tbl[y1] + x1;
  503.    a2 = pix_tbl[y2] + x2;
  504.    while (a1 <= a2)
  505.    {
  506.       for (i=0; i<w; i++)
  507.       {
  508.          pix_mem[a1++] = c;
  509.       }
  510.       a1 += NUMXPIXELS - w;
  511.       j++;
  512.    }
  513. }
  514.  
  515. union outcode
  516. {
  517.    struct
  518.    {
  519.       unsigned code0: 1;   /* x < 0 */
  520.       unsigned code1: 1;   /* y < 0 */
  521.       unsigned code2: 1;   /* x > MAXX */
  522.       unsigned code3: 1;   /* y > MAXY */
  523.    }  ocs;
  524.    short outcodes;
  525. };
  526.  
  527. void pix_lineclip( int x1, int y1, int x2, int y2, short color  )
  528. {
  529.    register union outcode oc1;
  530.    register union outcode oc2;
  531.    short inside;
  532.    short outside;
  533.    int temp;
  534.    
  535.    oc1.outcodes = 0; oc2.outcodes = 0;
  536.    oc1.ocs.code0 = ( x1 < 0 );
  537.    oc1.ocs.code1 = ( y1 < 0 );
  538.    oc1.ocs.code2 = ( x1 > MAXX );
  539.    oc1.ocs.code3 = ( y1 > MAXY );
  540.  
  541.    oc2.ocs.code0 = ( x2 < 0 );
  542.    oc2.ocs.code1 = ( y2 < 0 );
  543.    oc2.ocs.code2 = ( x2 > MAXX );
  544.    oc2.ocs.code3 = ( y2 > MAXY );
  545.  
  546.    inside = ((oc1.outcodes | oc2.outcodes) == 0);
  547.    outside = ((oc1.outcodes & oc2.outcodes) != 0);
  548.  
  549.    while( !outside && !inside )
  550.    {  if ( oc1.outcodes == 0 )
  551.       {  temp = x1; x1 = x2; x2 = temp;
  552.          temp = y1; y1 = y2; y2 = temp;
  553.          temp = oc1.outcodes;
  554.          oc1.outcodes = oc2.outcodes;
  555.          oc2.outcodes = temp;
  556.       }
  557.       
  558.       if ( oc1.ocs.code0 ) /*==== left ====*/
  559.       {
  560.          y1 += (long)(y2-y1) * (-x1) / (x2 - x1);
  561.          x1 = 0;
  562.       }
  563.       else if ( oc1.ocs.code1 ) /*==== right =====*/
  564.       {
  565.          x1 += (long)(x2-x1) * (-y1) / (y2 - y1);
  566. /*         x1 += (x2-x1) * ((-y1) / (y2 - y1)); */
  567.          y1 = 0;
  568.       }
  569.       else if ( oc1.ocs.code2 ) /*===== above ======*/
  570.       {
  571.          y1 += (long)(y2-y1) * (MAXX - x1) / (x2 - x1);
  572. /*         y1 += (y2-y1) * ((MAXY - x1) / (x2 - x1)); */
  573.          x1 = MAXX;
  574.       }
  575.       else if ( oc1.ocs.code3 ) /*====== below =====*/
  576.       {
  577.          x1 += (long)(x2 - x1) * (MAXY - y1) / (y2 - y1);
  578. /*         x1 += (x2 - x1) * ((MAXY - y1) / (y2 - y1)); */
  579.          y1 = MAXY;
  580.       }
  581.       oc1.outcodes = 0;
  582.       oc1.ocs.code0 = ( x1 < 0 );
  583.       oc1.ocs.code1 = ( y1 < 0 );
  584.       oc1.ocs.code2 = ( x1 > MAXX );
  585.       oc1.ocs.code3 = ( y1 > MAXY );
  586.       inside = ((oc1.outcodes | oc2.outcodes) == 0);
  587.       outside = ((oc1.outcodes & oc2.outcodes) != 0);
  588.    }
  589.    if ( inside )
  590.    {
  591.       pix_line( x1, y1, x2, y2, color );
  592.    }
  593. }
  594.